package com.kinyx.framework.db.daos;

import java.util.List;

import com.kinyx.framework.annotation.assist.Note;
import com.kinyx.framework.db.configs.DBConfigsHelper;
import com.kinyx.framework.db.entities.I_ID;
import com.kinyx.framework.db.sentence.defines.DeleteResSentence;
import com.kinyx.framework.db.sentence.defines.InsertResSentence;
import com.kinyx.framework.db.sentence.defines.SelectResSentence;
import com.kinyx.framework.db.sentence.defines.SelectSentence;
import com.kinyx.framework.db.sentence.defines.UpdateResSentence;
import com.kinyx.framework.db.sentence.str.SQL;
import com.kinyx.framework.enums.impl.ErrorCode1;
import com.kinyx.framework.exception.KRuntimeException;
import com.kinyx.framework.log.Log;
import com.kinyx.framework.log.Logger;
import com.kinyx.framework.vo.InPageData;
import com.kinyx.framework.vo.OutPageData;

/**
 * 数据访问实现类（JDBC）
 */
public abstract class JDBCDao implements _Dao_SQL, _Dao_Sentence_get {

	/** 日志对象 */
	private final Log logger = Logger.getLog(this.getClass());

	/** @return 配置键唯一标识 */
	public abstract String getKey();

	private DaoParam initDaoParam(final DaoParam dp) {
		dp.setIfLoggerIsNull(this.logger);
		return dp.configs(DBConfigsHelper.getDBConfigs(this.getKey()));
	}

	@SuppressWarnings("unchecked")
	@Override
	@Deprecated
	public <V> V queryValue(final DaoParam dp, final String sql, final List<Object> params, final Class<V> clazz) {
		return (V) JDBCDaoExecutor.executeQuery(this.initDaoParam(DaoParam.of(dp, DMLType.queryValue).sql(sql).params(params)), clazz, 0, null);
	}
	@SuppressWarnings("unchecked")
	@Override
	@Deprecated
	public <B> List<B> queryList(final DaoParam dp, final String sql, final List<Object> params, final Class<B> clazz, final int maxCount) {
		return (List<B>) JDBCDaoExecutor.executeQuery(this.initDaoParam(DaoParam.of(dp, DMLType.queryList).sql(sql).params(params)), clazz, maxCount, null);
	}
	@SuppressWarnings("unchecked")
	@Override
	@Deprecated
	public <B> B queryOne(final DaoParam dp, final String sql, final List<Object> params, final Class<B> clazz) {
		return (B) JDBCDaoExecutor.executeQuery(this.initDaoParam(DaoParam.of(dp, DMLType.queryOne).sql(sql).params(params)), clazz, 0, null);
	}
	@SuppressWarnings("unchecked")
	@Override
	@Deprecated
	public <B> OutPageData<B> queryPage(final DaoParam dp, final String sql, final List<Object> params, final Class<B> clazz, final InPageData pageData) {
		return (OutPageData<B>) JDBCDaoExecutor.executeQuery(this.initDaoParam(DaoParam.of(dp, DMLType.queryPage).sql(sql).params(params)), clazz, 0, null);
	}

	@Override
	@Deprecated
	public int change(final DaoParam dp) {
		return JDBCDaoExecutor.executeUpdate(this.initDaoParam(dp));
	}

	@Override
	@Deprecated
	public int batchChange(final DaoParam dp) {
		return JDBCDaoExecutor.executeUpdate(this.initDaoParam(dp));
	}

	@Override
	@Deprecated
	public <V> V getValue(final DaoParam dp, final SelectSentence select, final Class<V> clazz) {
		if (!select.isSQL()) { throw new KRuntimeException(ErrorCode1.CODE_ERROR_803); }
		return this.queryValue(dp, select.getSentence(), select.getParams(), clazz);
	}
	@Override
	@Deprecated
	public <B> List<B> getList(final DaoParam dp, final SelectSentence select, final Class<B> clazz) {
		if (!select.isSQL()) { throw new KRuntimeException(ErrorCode1.CODE_ERROR_803); }
		return this.queryList(dp, select.getSentence(), select.getParams(), clazz, select.getPageSize());
	}
	@Override
	@Deprecated
	public <B> B getOne(final DaoParam dp, final SelectSentence select, final Class<B> clazz) {
		if (!select.isSQL()) { throw new KRuntimeException(ErrorCode1.CODE_ERROR_803); }
		return this.queryOne(dp, select.getSentence(), select.getParams(), clazz);
	}
	@Override
	@Deprecated
	public <B> OutPageData<B> getPage(final DaoParam dp, final SelectSentence select, final Class<B> clazz) {
		if (!select.isSQL()) { throw new KRuntimeException(ErrorCode1.CODE_ERROR_803); }
		return this.queryPage(dp, select.getSentence(), select.getParams(), clazz, new InPageData().pageNumber(select.getPageNumber()).pageSize(select.getPageSize()));
	}

	@Override
	public <V> V getValue(final DaoParam dp, final SelectResSentence select, final Class<V> clazz) {
		if (!select.isSQL()) { throw new KRuntimeException(ErrorCode1.CODE_ERROR_803); }
		return this.queryValue(dp, select.getSentence(DBConfigsHelper.getDBConfigs(this.getKey())), select.getParams(), clazz);
	}
	@Override
	public <B> List<B> getList(final DaoParam dp, final SelectResSentence select, final Class<B> clazz) {
		if (!select.isSQL()) { throw new KRuntimeException(ErrorCode1.CODE_ERROR_803); }
		return this.queryList(dp, select.getSentence(DBConfigsHelper.getDBConfigs(this.getKey())), select.getParams(), clazz, select.getPageSize());
	}
	@Override
	public <B> B getOne(final DaoParam dp, final SelectResSentence select, final Class<B> clazz) {
		if (!select.isSQL()) { throw new KRuntimeException(ErrorCode1.CODE_ERROR_803); }
		return this.queryOne(dp, select.getSentence(DBConfigsHelper.getDBConfigs(this.getKey())), select.getParams(), clazz);
	}
	@Override
	public <B> OutPageData<B> getPage(final DaoParam dp, final SelectResSentence select, final Class<B> clazz) {
		if (!select.isSQL()) { throw new KRuntimeException(ErrorCode1.CODE_ERROR_803); }
		return this.queryPage(dp, select.getSentence(DBConfigsHelper.getDBConfigs(this.getKey())), select.getParams(), clazz, new InPageData().pageNumber(select.getPageNumber()).pageSize(select.getPageSize()));
	}

	@Override
	public int insert(final DaoParam dp, final InsertResSentence insert) {
		return this.change(DaoParam.of(dp, DMLType.insert).sql(insert.getSentence(DBConfigsHelper.getDBConfigs(this.getKey()))).params(insert.getParams()));
	}
	@Override
	public int update(final DaoParam dp, final UpdateResSentence update) {
		return this.change(DaoParam.of(dp, DMLType.update).sql(update.getSentence(DBConfigsHelper.getDBConfigs(this.getKey()))).params(update.getParams()));
	}
	@Override
	public int delete(final DaoParam dp, final DeleteResSentence delete) {
		return this.change(DaoParam.of(dp, DMLType.delete).sql(delete.getSentence(DBConfigsHelper.getDBConfigs(this.getKey()))).params(delete.getParams()));
	}

	/**
	 * 查询单个数据（使用主键）
	 * @param <E> 泛型
	 * @param dp 数据访问参数
	 * @param clazz 返回值类型
	 * @param id 主键
	 * @return 单个数据
	 */
	@SuppressWarnings("deprecation")
	@Note("仅支持实体类")
	public <E> E getOneById(final DaoParam dp, final Class<E> clazz, final String id) {
		return this.queryOne(dp, new SQL().s(String.format("SELECT * FROM %s WHERE ID = ?", DBConfigsHelper.getDBConfigs(this.getKey()).getTableInfo(clazz).getTableName())).p(id), clazz);
	}
	/**
	 * 保存对象
	 * <pre>
	 * 1、主键无值。新增数据。
	 * 2、主键有值。按照主键查表。
	 * 	2.1、无数据。新增数据。
	 * 	2.2、有数据。校验是否有字段修改。
	 * 		2.2.1、无字段修改。忽略。
	 * 		2.2.2、有字段修改。更新数据。
	 * </pre>
	 * @param dp 数据访问参数
	 * @param entity 实体类对象
	 */
	@Note("仅支持实体类")
	public void save(final DaoParam dp, final I_ID entity) {
		JDBCDaoExecutor.save(this, this.initDaoParam(DaoParam.of(dp, DMLType.saveEntity)), entity);
	}
	/**
	 * 删除对象
	 * <pre>
	 * 1、主键无值。忽略。
	 * 2、主键有值。按照主键查表。
	 * 	2.1、无数据。忽略。
	 * 	2.2、有数据。删除数据。
	 * </pre>
	 * @param dp 数据访问参数
	 * @param entity 实体类对象
	 */
	@Note("仅支持实体类")
	public void remove(final DaoParam dp, final I_ID entity) {
		JDBCDaoExecutor.remove(this, this.initDaoParam(DaoParam.of(dp, DMLType.deleteEntity)), entity);
	}

}
